{$MODE objfpc}
unit PythonTypes;

interface

	type
	  IntPtr = ^Integer;
	  UInt32 = Cardinal;
	  Int32 = Integer;
		Py_ssize_t = Cardinal;
		size_t = UInt32;
		Long = Int64;
		ULong = UInt64;
		PyObjectPtr = ^PyObject;
		PyObjectPtrPtr = ^PyObjectPtr;
		PyTypeObjectPtr = ^PyTypeObject;
		

		PyCFunction = function (obj, obj1: PyObjectPtr): PyObjectPtr; cdecl;
		PyCFunctionWithKeywords = function (obj, obj1, obj2: PyObjectPtr): PyObjectPtr; cdecl;
		PyNoArgsFunction = function (obj: PyObjectPtr): PyObjectPtr; cdecl;

		//
		// methodobject.h
		//

		PyMethodDefPtr = ^PyMethodDef;
		PyMethodDef = record
		    ml_name: PChar;		// The name of the built-in function/method
		    ml_meth: PyCFunction;	// The C function that implements it
		    ml_flags: Integer;	// Combination of METH_xxx flags, which mostly 
										// describe the args expected by the C func
		    ml_doc: PChar;		// The __doc__ attribute, or NULL
		end;
    PyMethodDefArr = Array Of PyMethodDef;

		PyCFunctionObject = record
		  //PyObject_HEAD
			ob_refcnt: 	Py_ssize_t;
			ob_type: 	PyTypeObjectPtr;

      m_ml: 		PyMethodDefPtr; // Description of the C function to call
		  m_self: 		PyObjectPtr; 	// Passed as 'self' arg to the C func, can be NULL
		  m_module: 	PyObjectPtr;  // The __module__ attribute, can be anything
		end;
		PyCFunctionObjectPtr = ^PyCFunctionObject;

		PyMethodChainPtr = ^PyMethodChain;
		PyMethodChain = record
		    methods: PyMethodDefPtr;			// Methods of this type
		    link: PyMethodChainPtr;			// NULL or base type
		end;
		
		//
		// PythonStructMember
		//
		memberlist = record
			// Obsolete version, for binary backwards compatibility
			name: PChar;
			typeId: Integer;
			offset: Integer;
			flags: Integer;
		end;

		PyMemberDefPtr = ^PyMemberDef;
		PyMemberDef = record
			// Current version, use this 
			name: PChar;
			typeId: Integer;
			offset: Py_ssize_t;
			flags: Integer;
			doc: PChar;
		end;

		
		//
		// descrobject
		//
		getter = function(obj: PyObjectPtr; p: Pointer): PyObjectPtr;
		setter = function(obj, obj1: PyObjectPtr; p: Pointer): Integer;

		wrapperfunc = function(self: PyObjectPtr; args: PyObjectPtr; wrapped: Pointer): PyObjectPtr; cdecl;
		wrapperfunc_kwds = function(self: PyObjectPtr; args: PyObjectPtr; wrapped: Pointer; kwds: PyObjectPtr): PyObjectPtr; cdecl;


		PyGetSetDefPtr = ^PyGetSetDef;
		PyGetSetDef = record
			name: PChar;
			getr: getter;
			setr: setter;
			doc: PChar;
			closure: Pointer;
		end;

		wrapperbase = record
			name: PChar;
			offset: Integer;
			functionP: Pointer;
			wrapper: wrapperfunc;
			doc: PChar;
			flags: Integer;
			name_strobj: PyObjectPtr;
		end;
		wrapperbasePtr = ^wrapperbase;

	// Various kinds of descriptor objects
		PyDescrObject = record
			//PyDescr_COMMON
			//PyObject_HEAD
			ob_refcnt: Py_ssize_t;
			ob_type: PyTypeObjectPtr;

			d_type: PyTypeObjectPtr;
			d_name: PyObjectPtr;
		end;

		PyMethodDescrObject = record
			//PyDescr_COMMON
			//PyObject_HEAD
			ob_refcnt: Py_ssize_t;
			ob_type: PyTypeObjectPtr;

			d_type: PyTypeObjectPtr;
			d_name: PyObjectPtr;

			d_method: PyMethodDefPtr;
		end;

		PyMemberDescrObject = record
			//PyDescr_COMMON
			//PyObject_HEAD
			ob_refcnt: Py_ssize_t;
			ob_type: PyTypeObjectPtr;

			d_type: PyTypeObjectPtr;
			d_name: PyObjectPtr;
			d_member: PyMemberDefPtr;
		end;

		PyGetSetDescrObject = record
			//PyDescr_COMMON
			//PyObject_HEAD
			ob_refcnt: Py_ssize_t;
			ob_type: PyTypeObjectPtr;

			d_type: PyTypeObjectPtr;
			d_name: PyObjectPtr;
			d_getset: PyGetSetDefPtr;
		end;

		PyWrapperDescrObject = record
			//PyDescr_COMMON
			//PyObject_HEAD
			ob_refcnt: Py_ssize_t;
			ob_type: PyTypeObjectPtr;

			d_type: PyTypeObjectPtr;
			d_name: PyObjectPtr;
			d_base: wrapperbasePtr;
			d_wrapped: Pointer; 		//This can be any function pointer
		end;

		//
		//object.h
		//
		freefunc = procedure (obj: Pointer);
		destructorProc = procedure (obj: PyObjectPtr);
		printfunc = function (obj: PyObjectPtr; var output: FILE; int: Integer): Integer;
		getattrfunc = function (obj: PyObjectPtr; atrr: PChar): PyObjectPtr;
		getattrofunc = function (obj, obj1: PyObjectPtr):  PyObjectPtr;
		setattrfunc = function (obj: PyObjectPtr; attr: PChar; val: PyObjectPtr): Integer;
		setattrofunc = function (obj, obj1, obj2: PyObjectPtr): Integer;
		cmpfunc = function (obj, obj1: PyObjectPtr): Integer;
		reprfunc = function (obj: PyObjectPtr): PyObjectPtr;
		hashfunc = function (obj: PyObjectPtr): Long;
		richcmpfunc = function (obj, obj1: PyObjectPtr; i: Integer): PyObjectPtr;
		getiterfunc = function (obj: PyObjectPtr): PyObjectPtr;
		iternextfunc = function (obj: PyObjectPtr): PyObjectPtr;
		descrgetfunc = function (obj, obj1, obj2: PyObjectPtr): PyObjectPtr;
		descrsetfunc = function (obj, obj1, obj2: PyObjectPtr): Integer;
		initproc = function (obj, obj1, obj2: PyObjectPtr): Integer;
		newfunc = function (pyType: PyTypeObjectPtr; obj, obj1: PyObjectPtr): PyObjectPtr;
		allocfunc = function (pyType: PyTypeObjectPtr; sz: Py_ssize_t): PyObjectPtr;

		{
		Type objects contain a string containing the type name (to help somewhat
		in debugging), the allocation parameters (see PyObject_New() and
		PyObject_NewVar()),
		and methods for accessing objects of the type.  Methods are optional, a
		nil pointer meaning that particular kind of access is not available for
		this type.  The Py_DECREF() macro uses the tp_dealloc method without
		checking for a nil pointer; it should always be implemented except if
		the implementation can guarantee that the reference count will never
		reach zero (e.g., for statically allocated type objects).

		NB: the methods for certain type groups are now contained in separate
		method blocks.
		}

		unaryfunc = function (obj: PyObjectPtr): PyObjectPtr;
		binaryfunc = function (obj, obj1: PyObjectPtr): PyObjectPtr;
		ternaryfunc = function (obj, obj1, obj2: PyObjectPtr): PyObjectPtr;
		inquiry = function (obj: PyObjectPtr): Integer;
		lenfunc = function (obj: PyObjectPtr): Py_ssize_t;
		coercion = function (var obj1, obj2: PyObjectPtr): Integer;
		// DEPRECATED typedef PyObjectPtr(*intintargfunc)(PyObjectPtr, int, int) Py_DEPRECATED(2.5);
		ssizeargfunc = function (obj: PyObjectPtr; sz: Py_ssize_t): PyObjectPtr;
		ssizessizeargfunc = function (obj: PyObjectPtr; sz, sz1: Py_ssize_t): PyObjectPtr;
		intobjargproc = function (obj: PyObjectPtr; int: Integer; obj1: PyObjectPtr): Integer;
		intintobjargproc = function (obj: PyObjectPtr; int, int1: Integer; obj1: PyObjectPtr): Integer;
		ssizeobjargproc = function (obj: PyObjectPtr; sz: Py_ssize_t; obj1: PyObjectPtr): Integer;
		ssizessizeobjargproc = function (obj: PyObjectPtr; sz, sz1: Py_ssize_t; obj1: PyObjectPtr): Integer;
		objobjargproc = function (obj, obj1, obj2: PyObjectPtr): Integer;

		// int-based buffer interface
		getreadbufferproc = function (obj: PyObjectPtr; int: Integer; var p: Pointer): Integer;
		getwritebufferproc = function (obj: PyObjectPtr; int: Integer; var p: Pointer): Integer;
		getsegcountproc = function (obj: PyObjectPtr; var int: Integer): Integer;
		getcharbufferproc = function (obj: PyObjectPtr; int: Integer; var c: PChar): Integer;

		// ssize_t-based buffer interface
		readbufferproc = function (obj: PyObjectPtr; sz: Py_ssize_t; var p: Pointer): Py_ssize_t;
		writebufferproc = function (obj: PyObjectPtr; sz: Py_ssize_t; var p: Pointer): Py_ssize_t;
		segcountproc = function (obj: PyObjectPtr; var sz: Py_ssize_t): Py_ssize_t;
		charbufferproc = function (obj: PyObjectPtr; sz: Py_ssize_t; var v: PChar): Py_ssize_t;

		objobjproc = function (obj, obj1: PyObjectPtr): Integer;
		visitproc = function (obj: PyObjectPtr; p: Pointer): Integer;
		traverseproc = function (obj: PyObjectPtr; proc: visitproc; p: Pointer): Integer;

		PyNumberMethods = record
			{	For numbers without flag bit Py_TPFLAGS_CHECKTYPES set, all
			   arguments are guaranteed to be of the object's type (modulo
			   coercion hacks -- i.e. if the type's coercion function
			   returns other types, then these are allowed as well).  Numbers that
			   have the Py_TPFLAGS_CHECKTYPES flag bit set should check *both*
			   arguments for proper type and implement the necessary conversions
			   in the slot functions themselves.}
			nb_add: binaryfunc;
			nb_subtract: binaryfunc;
			nb_multiply: binaryfunc;
			nb_divide: binaryfunc;
			nb_remainder: binaryfunc;
			nb_divmod: binaryfunc;
			nb_power: ternaryfunc;
			nb_negative: unaryfunc;
			nb_positive: unaryfunc;
			nb_absolute: unaryfunc;
			nb_nonzero: inquiry;
			nb_invert: unaryfunc;
			nb_lshift: binaryfunc;
			nb_rshift: binaryfunc;
			nb_and: binaryfunc;
			nb_xor: binaryfunc;
			nb_or: binaryfunc;
			nb_coerce: coercion;
			nb_int: unaryfunc;
			nb_long: unaryfunc;
			nb_float: unaryfunc;
			nb_oct: unaryfunc;
			nb_hex: unaryfunc;

			// Added in release 2.0 
			nb_inplace_add: binaryfunc;
			nb_inplace_subtract: binaryfunc;
			nb_inplace_multiply: binaryfunc;
			nb_inplace_divide: binaryfunc;
			nb_inplace_remainder: binaryfunc;
			nb_inplace_power: ternaryfunc;
			nb_inplace_lshift: binaryfunc;
			nb_inplace_rshift: binaryfunc;
			nb_inplace_and: binaryfunc;
			nb_inplace_xor: binaryfunc;
			nb_inplace_or: binaryfunc;

			// Added in release 2.2
			// The following require the Py_TPFLAGS_HAVE_CLASS flag
			nb_floor_divide: binaryfunc;
			nb_true_divide: binaryfunc;
			nb_inplace_floor_divide: binaryfunc;
			nb_inplace_true_divide: binaryfunc ;

			// Added in release 2.5
			nb_index: unaryfunc;
		end;

		PySequenceMethods = record
			sq_length: lenfunc;
			sq_concat: binaryfunc;
			sq_repeat: ssizeargfunc;
			sq_item: ssizeargfunc;
			sq_slice: ssizessizeargfunc;
			sq_ass_item: ssizeobjargproc;
			sq_ass_slice: ssizessizeobjargproc;
			sq_contains: objobjproc;
			// Added in release 2.0
			sq_inplace_concat: binaryfunc;
			sq_inplace_repeat: ssizeargfunc;
		end;

		PyMappingMethods = record
			mp_length: lenfunc;
			mp_subscript: binaryfunc;
			mp_ass_subscript: objobjargproc;
		end;

		PyBufferProcs = record
			bf_getreadbuffer: readbufferproc;
			bf_getwritebuffer: writebufferproc;
			bf_getsegcount: segcountproc;
			bf_getcharbuffer: charbufferproc;
		end;

		PyTypeObject = record
			// Object header details
			// PyObject_VAR_HEAD
			ob_refcnt: Py_ssize_t;
			ob_type: PyTypeObjectPtr;

			// For printing, in format "<module>.<name>"
			tp_name: PChar;
			// For allocation
			tp_basicsize, tp_itemsize: Py_ssize_t;

			// Methods to implement standard operations
			tp_dealloc: destructorProc;
			tp_print: 	printfunc;
			tp_getattr: getattrfunc;
			tp_setattr: setattrfunc;
			tp_compare: cmpfunc;
			tp_repr: 	reprfunc;

			// Method suites for standard classes
			tp_as_number: 		^PyNumberMethods;
			tp_as_sequence: 	^PySequenceMethods;
			tp_as_mapping: 	^PyMappingMethods;

			// More standard operations (here for binary compatibility)
			tp_hash: 		hashfunc;
			tp_call: 		ternaryfunc;
			tp_str: 			reprfunc;
			tp_getattro: 	getattrofunc;
			tp_setattro: 	setattrofunc;

			// Functions to access object as input/output buffer
			tp_as_buffer: ^PyBufferProcs;

			// Flags to define presence of optional/expanded features
			tp_flags: Long;

			tp_doc: PChar; // Documentation string

			// Assigned meaning in release 2.0
			// call function for all accessible objects
			tp_traverse: traverseproc;

			// delete references to contained objects
			tp_clear: inquiry;

			// Assigned meaning in release 2.1
			// rich comparisons
			tp_richcompare: richcmpfunc;

			// weak reference enabler
			tp_weaklistoffset: Py_ssize_t;

			// Added in release 2.2 
			// Iterators 
			tp_iter: getiterfunc;
			tp_iternext: iternextfunc;

			// Attribute descriptor and subclassing stuff
			tp_methods: PyMethodDefPtr;
			tp_members: PyMethodDefPtr;
			tp_getset: PyGetSetDefPtr;

			tp_base: PyTypeObjectPtr;
			tp_dict: PyObjectPtr;
			tp_descr_get: descrgetfunc;
			tp_descr_set: descrsetfunc;
			tp_dictoffset: Py_ssize_t;
			tp_init: initproc;
			tp_alloc: allocfunc;
			tp_new: newfunc;
			tp_free: freefunc; // Low-level free-memory routine
			tp_is_gc: inquiry; // For PyObject_IS_GC
			tp_bases: PyObjectPtr;
			tp_mro: PyObjectPtr; // method resolution order
			tp_cache: PyObjectPtr;
			tp_subclasses: PyObjectPtr;
			tp_weaklist: PyObjectPtr;
			tp_del: destructorProc;

			{#ifdef COUNT_ALLOCS
				/* these must be last and never explicitly initialized */
				Py_ssize_t tp_allocs;
				Py_ssize_t tp_frees;
				Py_ssize_t tp_maxalloc;
				struct _typeobject *tp_prev;
				struct _typeobject *tp_next;
			#endif}
		end;

		_typeobject = PyTypeObject;

		{
		/* PyObject_VAR_HEAD defines the initial segment of all variable-size
		 * container objects.  These end with a declaration of an array with 1
		 * element, but enough space is malloc'ed so that the array actually
		 * has room for ob_size elements.  Note that ob_size is an element count,
		 * not necessarily a byte count.
		 */}

		{
		#define PyObject_VAR_HEAD		\
			PyObject_HEAD			\
			Py_ssize_t ob_size; /* Number of items in variable part */
		#define Py_INVALID_SIZE (Py_ssize_t)-1
		}

		PyVarObject = record
			ob_refcnt: Py_ssize_t;
			ob_type: PyTypeObjectPtr;
			ob_size: Py_ssize_t; // Number of items in variable part
		end;

		// The *real* layout of a type object when allocated on the heap
		PyHeapTypeObject = record
			{ Note: there's a dependency on the order of these members
			   in slotptr() in typeobject.c . }
			ht_type: PyTypeObject;
			as_number: PyNumberMethods;
			as_mapping: PyMappingMethods;
			as_sequence: PySequenceMethods; 
							{ as_sequence comes after as_mapping,
							  so that the mapping wins when both
							  the mapping and the sequence define
							  a given operator (e.g. __getitem__).
							  see add_operators() in typeobject.c . }
			as_buffer: PyBufferProcs;
			ht_name, ht_slots :PyObjectPTr;
			// here are optional user slots, followed by the members.
		end;
		PyHeapTypeObjectPtr = ^PyHeapTypeObject;
		_heaptypeobject = PyHeapTypeObject;
		
		{
		/* Nothing is actually declared to be a PyObject, but every pointer to
		 * a Python object can be cast to a PyObject*.  This is inheritance built
		 * by hand.  Similarly every pointer to a variable-size Python object can,
		 * in addition, be cast to PyVarObject*.
		 */
		}		
		PyObject = record
			ob_refcnt: Py_ssize_t;
			ob_type: Pointer; //PyTypeObjectPtr;
		end;
		_object = PyObject;
		
implementation

end.